home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-10-24 | 72.5 KB | 2,475 lines | [TEXT/PJMM] |
- unit Analysis;
-
- {Analysis routines used by the NIH Image}
-
- interface
-
- uses
- Memory, QuickDraw, Packages, Menus, Events, Fonts, Scrap, ToolUtils, Resources, Errors, StandardFile, Palettes, globals, Utilities, LeastSquares, Graphics, file1, file2, Ellipse, Lut;
-
-
-
- procedure DoHistogram;
- procedure GetRectHistogram;
- procedure GetHistogram;
- procedure ShowContinuousHistogram;
- procedure ComputeResults;
- procedure FindThresholdingMode;
- procedure Measure;
- procedure UpdateRoiLineWidth;
- procedure DoProfilePlotOptions;
- procedure ShowResults;
- procedure PlotDensityProfile;
- procedure SetScale;
- procedure Calibrate;
- procedure ResetCounter;
- procedure DoMeasurementOptions;
- procedure DoPoints (event: EventRecord);
- procedure FindAngle (event: EventRecord);
- procedure SaveBlankField;
- procedure UndoLastMeasurement (DisplayResults: boolean);
- procedure MarkSelection (count: integer);
- procedure AutoOutline (start: point);
- procedure RedoMeasurement;
- procedure DeleteMeasurement;
- procedure AnalyzeParticles;
- procedure MakeNonStraightLineRoi (RoiKind: RoiTypeType);
- function isBinaryImage: boolean;
- function DoAPDialog: boolean;
-
-
- implementation
-
- const
- UnitsPopUpID = 6;
-
- var
- WandMode: (LUTMode, GrayMapMode, BinaryMode);
- GrayMapThreshold: integer;
- InfoForRedirect: InfoPtr;
- UnitsKind: UnitsType;
-
-
-
- {$PUSH}
- {$D-}
-
-
- procedure DoHistogramOfLine (data: ptr; var histogram: HistogramType; width: LongInt);
- {$IFC PowerPC}
- VAR
- line:LinePtr;
- i,value:integer;
- BEGIN
- line:=LinePtr(data);
- FOR i:=0 TO width-1 DO BEGIN
- value:=line^[i];
- histogram[value]:=histogram[value]+1;
- END;
- END;
- {$ELSEC}
- {a0=data}
- {a1=histogram}
- {d0=width}
- {d1=pixel value}
- inline
- $4E56, $0000, { link a6,#0}
- $48E7, $C0C0, { movem.l a0-a1/d0-d1,-(sp)}
- $206E, $000C, { move.l 12(a6),a0}
- $226E, $0008, { move.l 8(a6),a1}
- $202E, $0004, { move.l 4(a6),d0}
- $5380, { subq.l #1,d0}
- $4281, {L clr.l d1}
- $1218, { move.b (a0)+,d1}
- $E541, { asl.w #2,d1}
- $52B1, $1800, { addq.l #1,0(a1,d1.l)}
- $51C8, $FFF4, { dbra d0,L}
- $4CDF, $0303, { movem.l (sp)+,a0-a1/d0-d1}
- $4E5E, { unlk a6}
- $DEFC, $000C; { add.w #12,sp}
- {$ENDC}
-
-
- procedure GetRectHistogram;
- var
- width, i, NumberOfLines: integer;
- offset: LongInt;
- p: ptr;
- begin
- if TooWide then
- exit(GetRectHistogram);
- ShowWatch;
- for i := 0 to 255 do
- Histogram[i] := 0;
- with info^.RoiRect, info^ do begin
- offset := top * BytesPerRow + left;
- p := ptr(ord4(PicBaseAddr) + offset);
- width := right - left;
- NumberOfLines := bottom - top;
- end;
- if width > 0 then
- for i := 1 to NumberOfLines do begin
- DoHistogramOfLine(p, histogram, width);
- p := ptr(ord4(p) + info^.BytesPerRow);
- end
- end;
-
-
- procedure SetupRedirectedSampling;
- var
- info1, info2, SaveInfo: InfoPtr;
- SameCalibration: boolean;
- i: integer;
- begin
- InfoForRedirect := nil;
- if nPics <> 2 then begin
- PutError('There must be exactly two image windows open to do redirected sampling.');
- AnalyzingParticles := false;
- exit(SetupRedirectedSampling);
- end;
- Info1 := pointer(WindowPeek(PicWindow[1])^.RefCon);
- Info2 := pointer(WindowPeek(PicWindow[2])^.RefCon);
- if not EqualRect(info1^.PicRect, info2^.PicRect) then begin
- PutError('The image windows must be exactly the same size to do redirected sampling.');
- AnalyzingParticles := false;
- exit(SetupRedirectedSampling);
- end;
- if (Info1^.fit <> uncalibrated) or (Info2^.fit <> uncalibrated) then begin
- SameCalibration := true;
- if Info1^.fit <> Info2^.fit then
- SameCalibration := false;
- if Info1^.nCoefficients <> Info2^.nCoefficients then
- SameCalibration := false;
- for i := 1 to info1^.nCoefficients do
- if Info1^.Coefficient[i] <> Info2^.Coefficient[i] then
- SameCalibration := false;
- if not SameCalibration then begin
- PutError('Both image must be calibrated the same way to do redirected sampling.');
- AnalyzingParticles := false;
- exit(SetupRedirectedSampling);
- end;
- end;
- if info = info1 then
- InfoForRedirect := info2
- else
- InfoForRedirect := info1;
- end;
-
-
- procedure GetHistogram;
- var
- MaskLine, DataLine: LineType;
- width, i, vloc: integer;
- sum, sum2, count, OverFlows: LongInt;
- SaveInfo: InfoPtr;
- value: LongInt;
- trect: rect;
- begin
- if TooWide then
- exit(GetHistogram);
- ShowWatch;
- if RedirectSampling then begin
- SetupRedirectedSampling;
- if InfoForRedirect = nil then
- exit(GetHistogram);
- end
- else
- InfoForRedirect := nil;
- if not SetupMask then
- beep;
- SaveInfo := Info;
- for i := 0 to 255 do
- Histogram[i] := 0;
- if FitEllipse then
- ResetSums;
- trect := info^.RoiRect;
- with trect do begin
- width := right - left;
- for vloc := top to bottom - 1 do begin
- if InfoForRedirect <> nil then
- Info := InfoForRedirect
- else
- Info := SaveInfo;
- GetLine(left, vloc, width, DataLine);
- Info := UndoInfo;
- GetLine(left, vloc, width, MaskLine);
- if FitEllipse then
- ComputeSums(vloc - top, width, MaskLine);
- for i := 0 to width - 1 do
- if MaskLine[i] = BlackIndex then begin
- value := band(DataLine[i],255);
- histogram[value] := histogram[value] + 1;
- end;
- end;
- end;
- Info := SaveInfo;
- if not AnalyzingParticles then
- SetupUndo; {Needed for drawing "marching ants".}
- end;
-
-
- {$POP}
-
- procedure ComputeResults;
- var
- MaxCount, icount, isum, n: LongInt;
- i: integer;
- sum, sum2, ri, rcount, tSD, rmode, xc, yc: extended;
- Major, Minor, EllipseAngle, hcenter, vcenter, calValue: extended;
- MinCalibratedValue, MaxCalibratedValue, CalibratedMean: extended;
- IgnoreThresholding: boolean;
- ulength, clength: extended;
- begin
- with info^, results do begin
- case ThresholdingMode of
- DensitySlice: begin
- MinIndex := SliceStart;
- MaxIndex := SliceEnd;
- end;
- GrayMapThresholding: begin
- MinIndex := GrayMapThreshold;
- MaxIndex := 255;
- end;
- BinaryImage: begin
- MinIndex := BlackIndex;
- MaxIndex := BlackIndex;
- end;
- NoThresholding: begin
- MinIndex := 0;
- MaxIndex := 255;
- end;
- end;
- IgnoreThresholding := RedirectSampling or (IncludeHoles and (AnalyzingParticles or (CurrentTool = Wand)));
- if IgnoreThresholding then begin
- MinIndex := 0;
- MaxIndex := 255;
- end;
- while (histogram[MinIndex] = 0) and (MinIndex < 255) do
- MinIndex := MinIndex + 1;
- while (histogram[MaxIndex] = 0) and (MaxIndex > 0) do
- MaxIndex := MaxIndex - 1;
- MaxCount := 0;
- sum := 0.0;
- isum := 0;
- sum2 := 0.0;
- n := 0;
- minCalibratedValue := 10e100;
- maxCalibratedValue := -10e100;
- rmode := 0.0;
- imode := 0;
- for i := MinIndex to MaxIndex do begin
- calValue := cvalue[i];
- icount := histogram[i];
- rcount := icount;
- sum := sum + rcount * calValue;
- isum := isum + icount * i;
- ri := i;
- sum2 := sum2 + sqr(calValue) * rcount;
- n := n + icount;
- if icount > MaxCount then begin
- MaxCount := icount;
- rmode := cvalue[i];
- imode := i
- end;
- if calValue < minCalibratedValue then
- minCalibratedValue := calValue;
- if calValue > maxCalibratedValue then
- maxCalibratedValue := calValue;
- end;
- if ContinuousHistoGram then
- exit(ComputeResults);
- if n = 0 then begin
- minCalibratedValue := 0.0;
- maxCalibratedValue := 0.0;
- end;
- if n > 0 then begin
- CalibratedMean := sum / n;
- UncalibratedMean := isum / n
- end
- else begin
- CalibratedMean := 0.0;
- UncalibratedMean := 0.0
- end;
- IncrementCounter;
- mean^[mCount] := CalibratedMean;
- mMin^[mCount] := minCalibratedValue;
- mMax^[mCount] := maxCalibratedValue;
- if mCount <= MaxStandards then
- umean[mCount] := UncalibratedMean;
- if n > 0 then begin
- rcount := n;
- tSD := (rcount * Sum2 - sqr(sum)) / rcount;
- if tSD > 0.0 then
- tSD := sqrt(tSD / (rcount - 1.0))
- else
- tSD := 0.0
- end
- else
- tSD := 0.0;
- sd^[mCount] := tSD;
- PixelCount^[mCount] := n;
- ulength := 0.0;
- clength := 0.0;
- with RoiRect do
- case RoiType of
- RectRoi: begin
- uLength := ((right - left) + (bottom - top)) * 2.0;
- cLength := uLength;
- if SpatiallyCalibrated then
- cLength := ((right - left) / xScale + (bottom - top) / yScale) * 2.0;
- end;
- OvalRoi: begin
- uLength := pi * ((right - left) + (bottom - top)) / 2.0;
- cLength := uLength;
- if SpatiallyCalibrated then
- cLength := pi * ((right - left) / xScale + (bottom - top) / yScale) / 2.0;
- end;
- LineRoi, SegLineRoi, FreeLineRoi: begin
- GetLengthOrPerimeter(ulength, clength);
- nLengths := nLengths + 1;
- end;
- PolygonRoi, FreehandRoi, TracedRoi:
- if (LengthM in Measurements) or (nLengths > 0) or WandAdjustAreas then
- GetLengthOrPerimeter(ulength, clength);
- otherwise
- end;
- if SpatiallyCalibrated then
- plength^[mCount] := cLength
- else
- plength^[mcount] := uLength;
- if SpatiallyCalibrated then
- mArea^[mCount] := n / (xScale * yScale)
- else
- mArea^[mCount] := n;
- mode^[mCount] := rmode;
- if FitEllipse then begin
- GetEllipseParam(Major, Minor, EllipseAngle, xc, yc);
- if InvertYCoordinates then
- yc := PicRect.bottom - yc;
- if SpatiallyCalibrated then begin
- Major := Major / xScale;
- Minor := Minor / xScale;
- xc := xc / xScale;
- yc := yc / yScale;
- end;
- MajorAxis^[mCount] := Major * 2.0;
- MinorAxis^[mCount] := Minor * 2.0;
- orientation^[mCount] := EllipseAngle;
- xcenter^[mCount] := xc;
- ycenter^[mCount] := yc;
- end else begin
- MajorAxis^[mCount] := 0.0;
- MinorAxis^[mCount] := 0.0;
- orientation^[mCount] := 0.0;
- with RoiRect do begin
- xc := left + (right - left) / 2.0;
- yc := top + (bottom - top) / 2.0;
- if InvertYCoordinates then
- yc := PicRect.bottom - yc;
- if SpatiallyCalibrated then begin
- xc := xc / xScale;
- yc := yc / yScale;
- end;
- xcenter^[mCount] := xc;
- ycenter^[mCount] := yc;
- end;
- end;
- end; {with}
- measuring := true;
- InfoMessage := '';
- end;
-
-
- {$PUSH}
- {$D-}
-
-
- procedure FindThresholdingMode;
- begin
- with info^ do begin
- if DensitySlicing then
- ThresholdingMode := DensitySlice
- else if thresholding then begin
- ThresholdingMode := GrayMapThresholding;
- GrayMapThreshold := ColorStart;
- if GrayMapThreshold < 0 then
- GrayMapThreshold := 0;
- if GrayMapThreshold > 255 then
- GrayMapThreshold := 255;
- end
- else if BinaryPic then
- ThresholdingMode := BinaryImage
- else
- ThresholdingMode := NoThresholding;
- end;
- end;
-
-
- procedure Measure;
- var
- AutoSelectAll: boolean;
- SaveN: integer;
- begin
- if NotInBounds then
- exit(Measure);
- with info^ do begin
- FindThresholdingMode;
- if ThresholdingMode = BinaryImage then
- ThresholdingMode := NoThresholding;
- AutoSelectAll := not RoiShowing;
- if AutoSelectAll then
- SelectAll(false);
- if (RoiType = RectRoi) and (not RedirectSampling) then
- GetRectHistogram
- else
- GetHistogram;
- if MeasurementToRedo > 0 then begin
- SaveN := mCount;
- mCount := MeasurementToRedo - 1;
- ComputeResults;
- ShowInfo;
- mCount := SaveN;
- MeasurementToRedo := 0;
- UpdateList;
- end
- else begin
- ComputeResults;
- ShowInfo;
- AppendResults;
- if RoiType = LineRoi then
- if nLengths = 1 then
- if not (LengthM in Measurements) then
- UpdateList;
- end;
- RoiShowing := true;
- WhatToUndo := UndoMeasurement;
- if AutoSelectAll then
- KillRoi;
- UpdateScreen(OldRoiRect);
- end;
- end;
-
-
- procedure ShowHistogram;
- var
- htop: integer;
- tport: GrafPtr;
- hrect, prect, srect: rect;
- FirstTime: boolean;
- begin
- GetPort(tPort);
- FirstTime := HistoWindow = nil;
- if FirstTime then begin
- htop := ScreenHeight - hheight - 10;
- SetRect(HistoRect, hleft, htop, hleft + hwidth, htop + hheight);
- HistoWindow := NewWindow(nil, HistoRect, 'Histogram', true, NoGrowDocProc, nil, true, 0);
- WindowPeek(HistoWindow)^.WindowKind := HistoKind;
- end;
- if FirstTime or (VideoControl = nil) then
- SelectWindow(HistoWindow);
- SetPort(HistoWindow);
- InvalRect(HistoWindow^.PortRect);
- SetPort(tPort);
- end;
-
-
- procedure ShowContinuousHistogram;
- const
- skip = 10;
- var
- i, NumberOfLines: integer;
- offset: LongInt;
- p: ptr;
- begin
- with info^ do
- if (FrameGrabber = QTvdig) and (PictureType = FrameGrabberType) then
- CopyOffscreen(fgPixMap, osPort^.portPixMap, PicRect, PicRect);
- for i := 0 to 255 do
- Histogram[i] := 0;
- p := ptr(ptr(fgSlotBase));
- NumberOfLines := ((fgHeight) div skip) - 1;
- offset := fgRowBytes * skip;
- for i := 1 to NumberOfLines do begin
- DoHistogramOfLine(p, histogram, fgWidth);
- p := ptr(ord4(p) + offset);
- end;
- ThresholdingMode := NoThresholding;
- HistogramSliceStart := 0;
- HistogramSliceEnd := 255;
- ComputeResults;
- ShowHistogram;
- end;
-
-
- procedure DoHistogram;
- var
- AutoSelectAll: boolean;
- begin
- if NotInBounds then
- exit(DoHistogram);
- if digitizing then begin
- if ContinuousHistogram then
- ContinuousHistogram := false
- else begin
- ContinuousHistogram := true;
- if info <> NoInfo then
- with info^ do begin
- RoiType := NoRoi;
- RoiRect := SrcRect;
- end;
- end;
- exit(DoHistogram)
- end;
- AutoSelectAll := not info^.RoiShowing;
- if AutoSelectAll then
- SelectAll(false);
- if (info^.RoiType = RectRoi) and (not RedirectSampling) then
- GetRectHistogram
- else
- GetHistogram;
- ThresholdingMode := NoThresholding;
- ComputeResults;
- ShowCount := false;
- ShowInfo;
- ShowCount := true;
- FindThresholdingMode;
- case ThresholdingMode of
- DensitySlice: begin
- HistogramSliceStart := SliceStart;
- HistogramSliceEnd := SliceEnd;
- end;
- GrayMapThresholding: begin
- HistogramSliceStart := GrayMapThreshold;
- HistogramSliceEnd := 255;
- end;
- BinaryImage, NoThresholding: begin
- HistogramSliceStart := 0;
- HistogramSliceEnd := 255;
- end;
- end;
- ShowHistogram;
- UndoLastMeasurement(false);
- WhatToUndo := NothingToUndo;
- if AutoSelectAll then
- KillRoi;
- end;
-
-
- {$POP}
-
- procedure PlotDensityProfile;
- var
- hloc, vloc, value, width, height, i: integer;
- aLine: LineType;
- sum: array[0..MaxLine] of real;
- start, p1, p2: point;
- begin
- with info^ do
- if RoiShowing then
- case RoiType of
- LineRoi: begin
- PlotLineProfile;
- exit(PlotDensityProfile);
- end;
- FreeLineRoi, SegLineRoi, PolygonRoi, FreehandRoi, TracedRoi: begin
- PlotArbitraryLine;
- exit(PlotDensityProfile);
- end;
- end; {case}
- if NoSelection or NotRectangular or NotInBounds then
- exit(PlotDensityProfile);
- ShowWatch;
- with info^.RoiRect do begin
- width := right - left;
- height := bottom - top;
- start.h := left;
- start.v := bottom;
- if (width >= height) or (OptionKeyWasDown) then begin
- {Column Average Plot}
- if width > MaxLine then begin
- PlotTooLongMsg;
- exit(PlotDensityProfile);
- end;
- for i := 0 to width - 1 do
- sum[i] := 0.0;
- for vloc := top to bottom - 1 do begin
- GetLine(left, vloc, width, aLine);
- for i := 0 to width - 1 do
- sum[i] := sum[i] + cvalue[aLine[i]];
- end;
- for i := 0 to width - 1 do
- PlotData^[i] := sum[i] / height;
- PlotCount := width;
- PlotAvg := height;
- PlotStart.h := left;
- PlotStart.v := top + (bottom - top) div 2;
- PlotAngle := 0.0;
- ComputePlotMinAndMax;
- if ShowPlot then
- SetupPlot(start, false);
- end
- else begin
- {Row Average Plot}
- if height > MaxLine then begin
- PlotTooLongMsg;
- exit(PlotDensityProfile);
- end;
- for i := 0 to height - 1 do
- sum[i] := 0.0;
- for hloc := left to right - 1 do begin
- GetColumn(hloc, top, height, aLine);
- for i := 0 to height - 1 do
- sum[i] := sum[i] + cValue[aLine[i]];
- end;
- for i := 0 to height - 1 do
- PlotData^[i] := sum[i] / width;
- PlotCount := height;
- PlotAvg := width;
- PlotStart.h := left + (right - left) div 2;
- PlotStart.v := top;
- PlotAngle := 270.0;
- ComputePlotMinAndMax;
- if ShowPlot then
- SetupPlot(start, true);
- end;
- end; {with}
- end;
-
-
- procedure SetScaleUProc (d: DialogPtr; item: integer);
- {User proc for Set Scale dialog box}
- var
- str: str255;
- VersInfo: str255;
- r: rect;
- begin
- SetPort(d);
- GetDItemRect(d, item, r);
- DrawDropBox(r);
- GetMenuItemText(UnitsMenuH, ord(UnitsKind) + 1, str);
- DrawPopUpText(str, r);
- end;
-
-
- procedure SetScale;
- const
- MeasuredDistanceID = 3;
- KnownDistanceID = 4;
- AspectRatioID = 5;
- ScaleID = 7;
- UnitsTextID = 8;
- var
- mylog: DialogPtr;
- item, i: integer;
- SaveUnitsKind, OldUnitsKind, MenuUnitsKind: UnitsType;
- KnownDistance, MeasuredDistance, SaveScale, TempScale, CalibratedDistance: extended;
- UnitsPerCM, OldUnitsPerCM, SaveRawScale, SaveAspectRatio: extended;
- ignore, MenuItem: integer;
- str: str255;
- SaveUnits: UnitType;
- isLineSelection: boolean;
- ulength, clength: extended;
- r: rect;
- begin
- if SetScaleUserProc=nil
- then SetScaleUserProc:=NewRoutineDescriptor(@SetScaleUProc, uppUserItemProcInfo, GetCurrentISA);
- with info^ do begin
- if (not RoiShowing) and (CurrentTool = LineTool) and (NoInfo^.roiType = LineRoi) then
- RestoreRoi;
- isLineSelection := RoiShowing and (RoiType = LineRoi);
- InitCursor;
- if isLineSelection then begin
- GetLengthOrPerimeter(ulength, clength);
- MeasuredDistance := ulength;
- end
- else
- MeasuredDistance := 0.0;
- if not SpatiallyCalibrated then
- xUnit := 'pixel';
- GetUnitsKind(UnitsKind, UnitsPerCM);
- SaveUnits := xUnit;
- SaveUnitsKind := UnitsKind;
- SaveScale := xScale;
- SaveAspectRatio := PixelAspectRatio;
- KnownDistance := 0.0;
- mylog := GetNewDialog(10, nil, pointer(-1));
- SetDReal(MyLog, MeasuredDistanceID, MeasuredDistance, 2);
- SetDReal(MyLog, KnownDistanceID, KnownDistance, 2);
- SelectdialogItemText(MyLog, KnownDistanceID, 0, 32767);
- SetDReal(MyLog, AspectRatioID, PixelAspectRatio, 4);
- SetUProc(myLog, UnitsPopupID, handle(SetScaleUserProc));
- if UnitsKind = pixels then
- TempScale := 1.0
- else
- TempScale := xScale;
- if trunc(TempScale) = TempScale then
- SetDReal(MyLog, ScaleID, TempScale, 0)
- else
- SetDReal(MyLog, ScaleID, TempScale, 5);
- SetDString(MyLog, UnitsTextID, xUnit);
- setport(myLog);
- repeat
- ModalDialog(nil, item);
- if item = MeasuredDistanceID then
- MeasuredDistance := GetDReal(MyLog, MeasuredDistanceID);
- if item = KnownDistanceID then
- KnownDistance := GetDReal(MyLog, KnownDistanceID);
- if item = ScaleID then begin
- MeasuredDistance := GetDReal(MyLog, ScaleID);
- KnownDistance := 1;
- SetDReal(MyLog, MeasuredDistanceID, MeasuredDistance, 2);
- SetDReal(MyLog, KnownDistanceID, KnownDistance, 2);
- end;
- if item = AspectRatioID then begin
- PixelAspectRatio := GetDReal(MyLog, AspectRatioID);
- if PixelAspectRatio <= 0.0 then begin
- beep;
- PixelAspectRatio := 1.0;
- end;
- end;
- if item = UnitsPopUpID then begin
- OldUnitsKind := UnitsKind;
- OldUnitsPerCM := UnitsPerCM;
- GetDItemRect(myLog, item, r);
- InvertRect(r);
- MenuItem := PopUpMenu(UnitsMenuH, r.left, r.top, ord(UnitsKind) + 1);
- InvertRect(r);
- GetMenuItemText(UnitsMenuH, MenuItem, str);
- DrawPopUpText(str, r);
- UnitsKind := UnitsType(MenuItem - 1);
- GetXUnits(UnitsKind);
- if (UnitsType(MenuItem - 1) = OtherUnits) and (OldUnitsKind <> OtherUnits) then
- xUnit := 'unit';
- SetDString(MyLog, UnitsTextID, xUnit);
- GetUnitsKind(UnitsKind, UnitsPerCM);
- if (UnitsPerCM <> OldUnitsPerCM) and (UnitsPerCM <> 0.0) and (OldUnitsPerCM <> 0.0) then
- xScale := xScale * (OldUnitsPerCM / UnitsPerCM);
- if UnitsKind = Pixels then
- KnownDistance := 0.0;
- end;
- if (item = KnownDistanceID) or (item = MeasuredDistanceID) or (item = ScaleID) then
- if (UnitsKind = Pixels) and (item <> cancel) then
- PutError('Please select a measurent unit (not pixels) before setting or changing the scale.')
- else begin
- if (MeasuredDistance > 0.0) and (KnownDistance > 0.0) then
- xScale := MeasuredDistance / KnownDistance;
- end;
- if UnitsKind = pixels then
- TempScale := 1.0
- else
- TempScale := xScale;
- if item <> ScaleID then begin
- if (trunc(TempScale) = TempScale) or (TempScale >= 10000.0) then
- SetDReal(MyLog, ScaleID, TempScale, 0)
- else if TempScale < 0.01 then
- SetDReal(MyLog, ScaleID, TempScale, 6)
- else
- SetDReal(MyLog, ScaleID, TempScale, 3);
- end;
- if item = UnitsTextID then begin
- str := GetDString(myLog, item);
- TruncateString(str, maxUnit);
- xUnit := str;
- GetUnitsKind(UnitsKind, UnitsPerCM);
- GetDItemRect(myLog, UnitsPopUpID, r);
- InvalRect(r);
- end;
- until (item = ok) or (item = cancel);
- DisposeDialog(mylog);
- if item = cancel then begin
- xUnit := SaveUnits;
- UnitsKind := SaveUnitsKind;
- xScale := SaveScale;
- PixelAspectRatio := SaveAspectRatio;
- end
- else
- Changes := true;
- SpatiallyCalibrated := (xScale <> 0.0) and (xUnit <> 'pixel');
- if SpatiallyCalibrated then
- yScale := xScale / PixelAspectRatio
- else begin
- UnitsKind := Pixels;
- UnitsPerCm := 0.0;
- PixelAspectRatio:=1.0;
- end;
- UpdateTitleBar;
- if item<>cancel then begin
- NoInfo^.SpatiallyCalibrated:=SpatiallyCalibrated;
- NoInfo^.xUnit := xUnit;
- NoInfo^.xScale := xScale;
- NoInfo^.PixelAspectRatio := PixelAspectRatio;
- end;
- end; {with info^}
- end;
-
-
- {$PUSH}
- {$D-}
-
-
- procedure SetupCalibrationPlot;
- const
- hrange = 1024;
- hmax = 1023;
- vrange = 600;
- vmax = 599;
- SymbolSize = 11;
- var
- fRect, tRect: rect;
- svalue, range, hscale, vscale, MinV, MaxV: extended;
- tPort: GrafPtr;
- i, hloc, vloc: integer;
- SaveClipRegion: RgnHandle;
- pt: point;
- begin
- PlotLeftMargin := 60;
- PlotTopMargin := 15;
- PlotBottomMargin := 30;
- PlotRightMargin := 100;
- MinV := minCValue;
- MaxV := maxCValue;
- for i := 1 to nStandards do begin
- svalue := StandardValues[i];
- if svalue < MinV then
- MinV := svalue;
- if svalue > MaxV then
- MaxV := svalue;
- end;
- range := MaxV - MinV;
- PlotWidth := hrange div 3 + PlotLeftMargin + PlotRightMargin;
- PlotHeight := vrange div 3 + PlotTopMargin + PlotBottomMargin;
- PlotLeft := 64;
- PlotTop := 64;
- for i := 0 to 255 do
- PlotData^[i] := cvalue[i];
- PlotAvg := 1;
- PlotCount := 256;
- MakePlotWindow(PlotLeft, PlotTop, PlotWidth, PlotHeight);
- if PlotWindow = nil then
- exit(SetupCalibrationPlot);
- WindowPeek(PlotWindow)^.WindowKind := CalibrationPlotKind;
- SetRect(fRect, -SymbolSize, -SymbolSize, hmax + SymbolSize, vmax + SymbolSize);
- GetPort(tPort);
- SetPort(PlotWindow);
- SaveClipRegion := PlotWindow^.ClipRgn;
- RectRgn(PlotWindow^.ClipRgn, fRect);
- hscale := 256.0 / hrange;
- vscale := range / vrange;
- PlotPICT := OpenPicture(fRect);
- for i := 1 to nStandards do begin
- hloc := round(umean[i] / hscale);
- vloc := vmax - round((StandardValues[i] - minCValue) / vscale);
- SetRect(tRect, hloc - SymbolSize, vloc - SymbolSize, hloc + SymbolSize, vloc + SymbolSize);
- FrameOval(tRect);
- end;
- MoveTo(0, vmax - round((cvalue[0] - minCValue) / vscale));
- for i := 1 to 255 do begin
- hloc := round(i / hscale);
- vloc := vmax - round((cvalue[i] - minCValue) / vscale);
- LineTo(hloc, vloc);
- end;
- ClosePicture;
- PlotWindow^.ClipRgn := SaveClipRegion;
- InvalRect(PlotWindow^.PortRect);
- SetPort(tPort);
- SelectWindow(PlotWindow);
- end;
-
-
- procedure DoCurveFitting;
- var
- i: integer;
- XData, YData, YFit, Residuals, TempData: ColumnVector;
- Variance: extended;
- SumResidualsSqr, SumStandards, mean, SumMeanDiffSqr, DegreesOfFreedom: extended;
- str1, str2: str255;
- begin
- with info^ do begin
- ShowWatch;
- if fit = RodbardFit then { need to reverse x and y to fit Rodbard equation }
- for i := 1 to nStandards do begin
- XData[i] := StandardValues[i];
- YData[i] := umean[i];
- end
- else
- for i := 1 to nStandards do begin
- XData[i] := umean[i];
- YData[i] := StandardValues[i];
- end;
- case fit of
- StraightLine:
- nCoefficients := 2;
- Poly2:
- nCoefficients := 3;
- Poly3:
- nCoefficients := 4;
- Poly4:
- nCoefficients := 5;
- Poly5:
- nCoefficients := 6;
- ExpoFit:
- nCoefficients := 2;
- PowerFit:
- nCoefficients := 2;
- LogFit:
- nCoefficients := 2;
- RodbardFit:
- nCoefficients := 4;
- end;
- DegreesOfFreedom := nStandards - nCoefficients;
- if DegreesOfFreedom < 0 then begin
- FitGoodness := 0.0;
- NumToString(nCoefficients, str1);
- case fit of
- StraightLine:
- str2 := 'straight line';
- Poly2:
- str2 := '2nd degree polynomial';
- Poly3:
- str2 := '3rd degree polynomial';
- Poly4:
- str2 := '4th degree polynomial';
- Poly5:
- str2 := '5th degree polynomial';
- ExpoFit:
- str2 := 'exponential';
- PowerFit:
- str2 := 'power';
- LogFit:
- str2 := 'log';
- RodbardFit:
- str2 := 'Rodbard';
- end;
- str2 := concat(' standards to do ', str2, ' fitting.');
- PutError(concat('You need at least ', str1, str2));
- AbortMacro;
- fit:=Uncalibrated;
- exit(DoCurveFitting)
- end;
- DoSimplexFit(nStandards, nCoefficients, XData, YData, Coefficient, residuals);
- ZeroClip := true;
- for i := 1 to nStandards do
- if ydata[i] < 0.0 then
- ZeroClip := false;
- GenerateValues;
- SumResidualsSqr := 0.0;
- SumStandards := 0.0;
- if fit = RodbardFit then
- for i := 1 to nStandards do begin
- tempdata[i] := StandardValues[i];
- StandardValues[i] := umean[i];
- end;
- for i := 1 to nStandards do begin
- SumResidualsSqr := SumResidualsSqr + sqr(residuals[i]);
- SumStandards := SumStandards + StandardValues[i];
- end;
- FitSD := Sqrt(SumResidualsSqr / nStandards);
- mean := SumStandards / nStandards;
- SumMeanDiffSqr := 0.0;
- for i := 1 to nStandards do
- SumMeanDiffSqr := SumMeanDiffSqr + sqr(StandardValues[i] - Mean);
- if (SumMeanDiffSqr > 0.0) and (DegreesOfFreedom <> 0) then
- FitGoodness := 1 - (SumResidualsSqr / DegreesOfFreedom) * ((nStandards - 1) / SumMeanDiffSqr)
- else
- FitGoodness := 1.0;
- if fit = RodbardFit then
- for i := 1 to nStandards do
- StandardValues[i] := tempdata[i];
- end;
- info^.changes := true;
- end;
-
-
- procedure GetStandardsFromFile (mylog: DialogPtr; FirstLevelID, FirstStandardID: integer);
- var
- fname, str: str255;
- RefNum, i, nColumns, nValues: integer;
- rLine: RealLine;
- begin
- RefNum := 0;
- if not GetTextFile(fname, RefNum) then
- exit(GetStandardsFromFile);
- InitTextInput(fname, RefNum);